package com.xbjtech.ticketsystem.config.bean.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

@Component
public class RedisManager implements IRedisManager {

    @Autowired
    RedisTemplate<Object, Object> redisTemplate;

    @Override
    public byte[] get(byte[] key) {
        return redisTemplate.execute(new RedisCallback<byte[]>() {
            @Override
            public byte[] doInRedis(RedisConnection redisConnection) throws DataAccessException {
                return redisConnection.get(key);
            }
        });
    }

    @Override
    public byte[] set(byte[] key, byte[] value, int expire) {
        return redisTemplate.execute(new RedisCallback<byte[]>() {
            @Override
            public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
                connection.set(key, value);
                connection.expire(key, expire);
                return value;
            }
        });
    }

    @Override
    public void del(byte[] key) {
        redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                connection.del(key);
                return true;
            }
        });
    }

    @Override
    public Long dbSize(byte[] pattern) {
        long dbSize = redisTemplate.execute(new RedisCallback<Long>() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                long count = 0;
                Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(new String(pattern)).count(1000).build());
                while (cursor.hasNext()) {
                    cursor.next();
                    count++;
                }
                return count;
            }
        });
        return dbSize;
    }

    @Override
    public Set<byte[]> keys(byte[] pattern) {
        return redisTemplate.execute(new RedisCallback<Set<byte[]>>() {
            @Override
            public Set<byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
                Set<byte[]> binaryKeys = new HashSet<>();
                Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(new String(pattern)).count(1000).build());
                while (cursor.hasNext()) {
                    binaryKeys.add(cursor.next());
                }
                return binaryKeys;
            }
        });
    }
}
